package de.szut.database;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import de.szut.entity.*;
import de.szut.impl.*;
import de.szut.interfaces.PointsDao;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * This class is used to create, upgrade and delete database and their tables.
 * It also creates all necessary DAO objects and grants access to them
 * <p/>
 * Created by dzebcuks on 19.08.13.
 */
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {

    /**
     * Database name
     */
    private static final String DATABASE_NAME = "splasher_database"; //$NON-NLS-1$

    /**
     * Version of the database (increase this, if any entities were updated)
     */
    private static final int DATABASE_VERSION = 23;

    private static DatabaseHelper instance = null;

    private BaseAbilityDaoImpl baseAbilityDao;

    private UpgradeAbilityDaoImpl upgradeAbilityDao;

    private AbilityTreeDaoImpl abilityTreeDao;

    private CountryDaoImpl countryDao;

    private Context context;

    private PointsDao pointsDao;

    private List<Class> tableClasses = new ArrayList<Class>(Arrays.asList(AbilityTree.class, AbilityUpgrade.class, BaseAbility.class, Modifier.class, ModifierValue.class, Country.class, Points.class));

    /**
     * Constructor... (needed by API)
     *
     * @param context
     */
    private DatabaseHelper(final Context context) {
        super(context,DATABASE_NAME, null, DATABASE_VERSION);
        this.context = context;
    }

    /**
     * Returns the instance
     *
     * @param ctx
     * @return
     */
    public static DatabaseHelper getInstance(final Context ctx) {
        if (instance == null) {
            instance = new DatabaseHelper(ctx);
        }
        return instance;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCreate(final SQLiteDatabase database,
                         final ConnectionSource connectionSource) {

        try {
            for(Class tableClass : this.tableClasses){
                TableUtils.createTableIfNotExists(connectionSource, tableClass);
            }
        } catch (final SQLException e) {
            Log.e(DatabaseHelper.class.getName(),
                    "Unable to create datbases", e); //$NON-NLS-1$
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onUpgrade(final SQLiteDatabase database,
                          final ConnectionSource connectionSource, final int oldVer,
                          final int newVer) {
        try {
            for(Class tableClass : this.tableClasses){
                TableUtils.dropTable(connectionSource, tableClass, true);
            }
            this.onCreate(database, connectionSource);
        } catch (final SQLException e) {
            Log.e(DatabaseHelper.class.getName(),
                    "Unable to upgrade database from version " + oldVer + " to new " + newVer,
                    e); //$NON-NLS-1$ //$NON-NLS-2$
        }
    }

    public void resetDatabase(){
        for(Class tableClass : this.tableClasses){
            try {
                TableUtils.clearTable(this.getConnectionSource(), tableClass);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public BaseAbilityDaoImpl getBaseAbilityDao() {
        if (this.baseAbilityDao == null) {
            try {
                this.baseAbilityDao = DaoManager.createDao(
                        this.getConnectionSource(), BaseAbility.class);
            } catch (final SQLException e) {
                Log.e(e.getClass().getName(), e.getMessage(), e);
            }
        }
        return this.baseAbilityDao;
    }

    public UpgradeAbilityDaoImpl getUpgradeAbilityDao() {
        if (this.upgradeAbilityDao == null) {
            try {
                this.upgradeAbilityDao = DaoManager.createDao(
                        this.getConnectionSource(), AbilityUpgrade.class);
            } catch (final SQLException e) {
                Log.e(e.getClass().getName(), e.getMessage(), e);
            }
        }
        return this.upgradeAbilityDao;
    }

    public AbilityTreeDaoImpl getAbilityTreeDao() {
        if (this.abilityTreeDao == null) {
            try {
                this.abilityTreeDao = DaoManager.createDao(
                        this.getConnectionSource(), AbilityTree.class);
            } catch (final SQLException e) {
                Log.e(e.getClass().getName(), e.getMessage(), e);
            }
        }
        return this.abilityTreeDao;
    }

    public CountryDaoImpl getCountryDao() {
        if (this.countryDao == null) {
            try {
                this.countryDao = DaoManager.createDao(
                        this.getConnectionSource(), Country.class);
            } catch (final SQLException e) {
                Log.e(e.getClass().getName(), e.getMessage(), e);
            }
        }
        return this.countryDao;
    }

    public PointsDao getPointsDao(){
        if (this.pointsDao == null) {
            try {
                this.pointsDao = DaoManager.createDao(
                        this.getConnectionSource(), Points.class);
            } catch (final SQLException e) {
                Log.e(e.getClass().getName(), e.getMessage(), e);
            }
        }
        return this.pointsDao;
    }
}
